package com.firewolf.realms;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.firewolf.entities.User;
import com.firewolf.service.UserService;

public class UserRealm extends AuthorizingRealm {

	private UserService userService;
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String uname = principals.getPrimaryPrincipal().toString();
		//实际项目中角色可能是到数据库中查询出来的
		Set<String> roles = new HashSet<>();
		roles.add("user");
		if("li".equals(uname)){
			roles.add("admin");
		}
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

		// 1.获取用户名
		String username = (String) token.getPrincipal();
		// UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		// String username = upToken.getUsername();
		System.out.println("userService : "+userService);
		// 2.根据用户名去数据库查询用户记录
		User user = userService.findByUsername(username);

		// 3.如果用户不存在，抛出UnknownAccountException异常，
		if (user == null) {
			throw new UnknownAccountException();// 没找到帐号
		}

		// 4.如果账号被锁定，抛出LockedAccountException
		if (Boolean.TRUE.equals(user.getLocked())) {
			throw new LockedAccountException(); // 帐号锁定
		}

		// 5.根据用户信息的情况，决是否抛出其他的AuthenticationException异常

		// 6.构建AuthenticationInfo并且返回通常使用的实现类为：SimpleAuthenticationInfo
		// 这些信息是从数据库获取的
		// 1).principal：认证的实体信息，可以是username，也可以是数据表对应的用户实体对象
		// 2).credentials:密码
		// 3).realmName ： 当前Realm的名字，调用父类的getName方法就可以了
		// 4).credentialsSalt：盐值

		String principal = user.getUsername();
		String hashedCredentials = user.getPassword();
		String realmName = getName();
		ByteSource credentialsSalt = ByteSource.Util.bytes(user.getCredentialsSalt());

		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt,
				realmName);
		
		return info;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

}
